package mornd.test1;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.event.EventListener;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * @author: mornd
 * @dateTime: 2023/5/12 - 23:00
 *
 * spring的事件与监听器(默认同步执行，若需要异步执行，只需添加线程池即可)
 * 核心组件：
 *          发布者：实现 ApplicationEventPublisher 接口，或者 applicationContext 本身
 *          监听器：实现 ApplicationListener 接口，或者方法上添加 @EventListener 注解
*           事件对象：（继承ApplicationEvent）
 */
@ComponentScan
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
        MyService bean = context.getBean(MyService.class);
        bean.doBusiness();
    }

    // 自定义发送短信事件
    static class SmsEvent extends ApplicationEvent {

        public SmsEvent(Object source) {
            super(source);
        }
    }

    // 自定义发送邮件事件
    static class MailEvent extends ApplicationEvent {

        public MailEvent(Object source) {
            super(source);
        }
    }

    @Slf4j
    @Component
    static class MyService {
        @Autowired
        private ApplicationEventPublisher publisher;

        public void doBusiness() {
            log.debug("主线任务");

            publisher.publishEvent(new MailEvent("msg"));
            publisher.publishEvent(new SmsEvent("msg"));
        }
    }

    // 方式一：自定义监听器，泛型表示只处理 短信事件
    @Slf4j
    @Component
    static class SmsListener implements ApplicationListener<SmsEvent> {

        @Override
        public void onApplicationEvent(SmsEvent event) {
            System.out.println(this + "收到事件：" + event.getSource());
            log.debug("发送短信");
        }
    }

    @Slf4j
    @Component
    static class MailListener implements ApplicationListener<MailEvent> {

        @Override
        public void onApplicationEvent(MailEvent event) {
            System.out.println(this + "收到事件：" + event.getSource());
            log.debug("发送邮件");
        }
    }

    // 方式二：注解方式实现监听器
    @Slf4j
    @Component
    static class MyListener {
        @EventListener
        public void listen(MailEvent event) {
            System.out.println(this + "收到事件：" + event.getSource());
            log.debug("其它业务处理");
        }
    }
    @Bean // 线程池
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("自定义异步线程池-");
        return executor;
    }

    // SimpleApplicationEventMulticaster 才是真正执行发布事件的对象
    @Bean("applicationEventMulticaster") // bean 名称需指定为 applicationEventMulticaster 才有效
    public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor taskExecutor) {
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        multicaster.setTaskExecutor(taskExecutor);
        return multicaster;
    }
}
